package org.genntii.smuserserver.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jthinking.common.util.ip.IPInfo;
import com.jthinking.common.util.ip.IPInfoUtils;
import jakarta.annotation.Resource;
import org.genntii.smcommon.constant.ClientConstant;
import org.genntii.smcommon.constant.ExceptionConstant;
import org.genntii.smcommon.exception.UserNotFoundException;
import org.genntii.smcommon.properties.JwtProperties;
import org.genntii.smcommon.utils.JwtUtil;
import org.genntii.smdomain.entity.User;
import org.genntii.smdomain.vo.SubscribeNumVO;
import org.genntii.smdomain.vo.UserVO;
import org.genntii.smuserserver.client.UserSubscribeClient;
import org.genntii.smuserserver.domain.LoginDTO;
import org.genntii.smuserserver.mapper.UserMapper;
import org.genntii.smuserserver.service.LoginService;
import org.genntii.smuserserver.utils.IpUtil;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Objects;


@Service
public class LoginServiceImpl extends ServiceImpl<UserMapper, User> implements LoginService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private JwtProperties jwtProperties;

    @Resource
    private UserSubscribeClient userSubscribeClient;



    @Override
    public UserVO login(LoginDTO loginDTO, String clientName, String ip) {
        User u;

        try{
            u = userMapper.selectUserByUsername(loginDTO.getUsername());
            if (Objects.isNull(u)){
                throw new UserNotFoundException(ExceptionConstant.USER_NOT_FOUND_EXCEPTION);
            }
        }catch (Exception e){
            throw new UserNotFoundException(ExceptionConstant.USER_NOT_FOUND_EXCEPTION);
        }

        if (!BCrypt.checkpw(loginDTO.getPassword(),u.getPassword())){
            throw new UserNotFoundException(ExceptionConstant.PASSWORD_ERROR_EXCEPTION);
        }


        Map<String, Object> claims = Map.of("id",u.getId(),"username",u.getUsername());

        String token;
        if (clientName.equals(ClientConstant.ADMIN_CLIENT)){
            token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(), jwtProperties.getAdminTtl(), claims);
        } else if (clientName.equals(ClientConstant.USER_CLIENT)) {
            token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(),claims);
        } else if (clientName.equals(ClientConstant.DEVELOPER_CLIENT)) {
            token = JwtUtil.createJWT(jwtProperties.getDevSecretKey(),jwtProperties.getDevTtl(),claims);
        }else {
            throw new HeadlessException("请求头有误");
        }


        userMapper.updateLoginTime(LocalDateTime.now(),u.getId());
        SubscribeNumVO subscribeNumVO = userSubscribeClient.getSubscribeNum(u.getId()).getData();
        UserVO vo = UserVO.builder()
                .id(u.getId())
                .username(u.getUsername())
                .nickname(u.getNickname())
                .description(u.getDescription())
                .email(u.getEmail())
                .avatar(u.getAvatar())
                .cityCode(u.getCityCode())
                .gender(u.getGender())
                .token(token)
                .backgroundImage(u.getBackgroundImage())
                .followerCount(subscribeNumVO.getSubscribeNum())
                .subscriberCount(subscribeNumVO.getSubscribedNum())
                .build();
        ObjectMapper objectMapper = new ObjectMapper();

        if (u.getBirthday() != null){
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            vo.setBirthday(u.getBirthday().format(fmt));
        }

        DateTimeFormatter fmtDateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        vo.setLoginTime(LocalDateTime.now().format(fmtDateTime));
        vo.setCreateTime(u.getCreateTime().format(fmtDateTime));

        if (!ip.equals(IpUtil.LOCAL_IP)){
            IPInfo ipInfo = IPInfoUtils.getIpInfo(ip);
            vo.setCityName(ipInfo.getProvince().isEmpty()? ipInfo.getProvince() : ipInfo.getCountry());
        }else vo.setCityName("测试环境");
        return vo;
    }
}
